#region Using Statements
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
#endregion

namespace MyFirstXNAGame.Source.Sprites
{
    public abstract class Sprite
    {
        public bool accelerateX = true;
        public bool accelerateY = true;
        protected Random random = new Random();
        public Texture2D texture;
        public Vector2 maxVelocity = new Vector2(999999.9f, 999999.9f);
        public Vector2 velocity;
        public Vector2 deceleration;
        public Vector2 acceleration;
        public Vector2 levelOrigin;
        public Rectangle bounds;
        public Rectangle lastCollidedCollisionBox;

        public Rectangle animationFrame = new Rectangle(0,0,0,0);
        public int lastAnimatedTime = 0;
        public int frame = 0;
        public int numFrames = 1;
        public int frameRow = 0;
        public Color color;        
        public SpriteEffects spriteEffects;
        public float scale;
        public float layer;

        public abstract bool update(float xOrigin, float yOrigin, int width, int height, GameTime gameTime, ArrayList environment, Vector2 theOrigin);
        public abstract Rectangle getBounds();
        public abstract ArrayList getCollisionBox();
        public abstract void onCollission(Sprite other);
        public abstract void input();

        public void init()
        {
            this.bounds = new Rectangle();
            this.spriteEffects = SpriteEffects.None;
            this.scale = 1.0f;
            this.layer = 1.0f;
            this.deceleration = new Vector2(0.0f, 0.0f);
            levelOrigin = new Vector2();
        }
        public void animate(int milliseconds)
        {
            if (velocity.X == 0)
            {
                frameRow = 0;
            }
            else
            {
                if (velocity.X < 0)
                {
                    spriteEffects = SpriteEffects.FlipHorizontally;
                }
                else if (velocity.X > 0)
                {
                    spriteEffects = SpriteEffects.None;
                }
                frameRow = 1;
            }
            if (milliseconds % 50 == 0 && lastAnimatedTime != milliseconds)
            {
                lastAnimatedTime = milliseconds;
                frame++;
                if (frame == numFrames)
                {
                    frame = 0;
                }
            }

        }
        protected void accelerate(GameTime gameTime)
        {
            if (accelerateX)
            {
                velocity.X += acceleration.X * (float)gameTime.ElapsedGameTime.TotalSeconds;
            }
            if (accelerateY)
            {
                velocity.Y += acceleration.Y * (float)gameTime.ElapsedGameTime.TotalSeconds;
            }

            if (velocity.X > maxVelocity.X)
            {
                velocity.X = maxVelocity.X;
            }
            else if (velocity.X < maxVelocity.X * -1)
            {
                velocity.X = maxVelocity.X * -1;
            }
            if (velocity.Y > maxVelocity.Y)
            {
                velocity.Y = maxVelocity.Y;
            }
            else if (velocity.Y < maxVelocity.Y * -1)
            {
                velocity.Y = maxVelocity.Y * -1;
            }
        }
        protected void decelerate(GameTime gameTime)
        {
            if (velocity.X > 0)
            {
                velocity.X -= deceleration.X * (float)gameTime.ElapsedGameTime.TotalSeconds;
                if (velocity.X < 0) velocity.X = 0;
            }
            else if (velocity.X < 0)
            {
                velocity.X += deceleration.X * (float)gameTime.ElapsedGameTime.TotalSeconds;
                if (velocity.X > 0) velocity.X = 0;
            }
            if (velocity.Y > 0)
            {
                velocity.Y -= deceleration.Y * (float)gameTime.ElapsedGameTime.TotalSeconds;
                if (velocity.Y < 0) velocity.Y = 0;
            }
            else if (velocity.Y < 0)
            {
                velocity.Y += deceleration.Y * (float)gameTime.ElapsedGameTime.TotalSeconds;
                if (velocity.Y > 0) velocity.Y = 0;
            }
        }
        protected void updateX(float xOrigin, int width, GameTime gameTime, Vector2 movement, float xMin)
        {
            levelOrigin.X += movement.X;
            if (levelOrigin.X < 0)
            {
                levelOrigin.X = 0;
                velocity.X *= -1;
            }
            else if (levelOrigin.X > width)
            {
                levelOrigin.X = width;
                velocity.X *= -1;
            }
            bounds.X = (int)(levelOrigin.X - xMin);
        }
        protected void updateY(float yOrigin, int height, GameTime gameTime, Vector2 movement, float yMin)
        {
            levelOrigin.Y += movement.Y;
            if (levelOrigin.Y < 0)
            {
                levelOrigin.Y = 0;
                velocity.Y *=-1;
            }
            else if (levelOrigin.Y > height)
            {
                levelOrigin.Y = height;
                velocity.Y *= -1;
            }
            bounds.Y = (int)(levelOrigin.Y - yMin);
        }
        protected Sprite detectCollisions(ArrayList environment)
        {
            ArrayList avatarCollisionBox = getCollisionBox();
            foreach (Sprite s in environment)
            {
                ArrayList spriteCollisionBox = s.getCollisionBox();
                foreach (Rectangle acb in avatarCollisionBox)
                {
                    foreach (Rectangle scb in spriteCollisionBox)
                    {
                        if (acb.Intersects(scb))
                        {
                            lastCollidedCollisionBox = acb;
                            s.lastCollidedCollisionBox = scb;
                            return s;
                        }
                    }
                }
            }
            return null;
        }

        public Rectangle getAnimationFrame()
        {
            animationFrame = new Rectangle((frame * texture.Width / numFrames), frameRow * bounds.Height, bounds.Width, bounds.Height);
            return animationFrame;
        }
        protected ArrayList getDefaultCollisionBox()
        {
            ArrayList result = new ArrayList();
            result.Add(new Rectangle((int)levelOrigin.X, (int)levelOrigin.Y, bounds.Width, bounds.Height));
            return result;
        }
    }
}
